# Copyright 2022 Flant JSC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

{!{/*
  Multifile generator of suspend workflows.

  One workflow file for each channel: suspend-alpha.yml, suspend-beta.yml, etc.

  The only reason to use separate files for each channel
  is a filtering on 'Actions' page.

*/}!}

{!{- range $channel := slice "alpha" "beta" "early-access" "stable" "rock-solid" -}!}
{!{- $ctx := dict "channel" $channel }!}
{!{- $outFile := printf "suspend-%s.yml" $channel }!}
{!{- $outPath := filepath.Join (getenv "OUTDIR") (toLower $outFile) }!}
{!{- tmpl.Exec "suspend_channel_workflow_template" $ctx | file.Write $outPath }!}
{!{- end -}!}

{!{- define "suspend_channel_workflow_template" -}!}
{!{- $channel := .channel -}!}
{!{- $workflowName := printf "Suspend the %s" $channel -}!}
# Copyright 2022 Flant JSC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


name: '{!{ $workflowName }!}'

on:
  workflow_dispatch:
    inputs:
      issue_id:
        description: 'Id of issue where label was set'
        required: false
      issue_number:
        description: 'Number of issue where label was set'
        required: false
      comment_id:
        description: 'Id of comment in issue where to put workflow run status'
        required: false
      suspend_tag:
        description: 'Set to suspend specified tag'
        required: false

env:
{!{ tmpl.Exec "werf_envs" | strings.Indent 2 }!}
  DEPLOY_CHANNEL: {!{ .channel }!}

# Note: no concurrency section for suspend workflows.

jobs:
{!{ tmpl.Exec "git_info_job" . | strings.Indent 2 }!}

  detect_version:
    name: Detect version
    needs:
      - git_info
    runs-on: ubuntu-latest
    outputs:
      version: ${{steps.detect_version.outputs.version}}
    steps:
      - name: Detect version
        id: detect_version
        env:
          CI_COMMIT_TAG: ${{needs.git_info.outputs.ci_commit_tag}}
          CI_COMMIT_REF_NAME: ${{needs.git_info.outputs.ci_commit_ref_name}}
          SUSPEND_TAG: ${{ github.event.inputs.suspend_tag }}
        run: |
          if [[ -n ${SUSPEND_TAG} ]] ; then
            echo "::notice title=Suspend version::Workflow started from '${CI_COMMIT_REF_NAME}', but suspend_tag input is set. Use '${SUSPEND_REVISION}' as suspend version."
            echo "version=${SUSPEND_TAG}" >> $GITHUB_OUTPUT
            exit 0
          fi
          if [[ -n ${CI_COMMIT_TAG} ]] ; then
            echo "::notice title=Suspend version::Workflow started from tag '${CI_COMMIT_TAG}'. Use it as suspend version."
            echo "version=${CI_COMMIT_TAG}" >> $GITHUB_OUTPUT
            exit 0
          fi

          echo "::error title=Wrong environment::Seems you try to suspend branch '${CI_COMMIT_REF_NAME}'. Use suspend_tag input or run workflow from tag."
          exit 1


  run_suspend:
    name: Suspend ${{needs.detect_version.outputs.version}} on {!{ .channel }!} channel
    environment:
      name: {!{ .channel }!}
    needs:
      - git_info
      - detect_version
    runs-on: [self-hosted, regular]
    steps:
{!{ tmpl.Exec "started_at_output" . | strings.Indent 6 }!}
{!{ tmpl.Exec "checkout_from_event_ref_step" . | strings.Indent 6 }!}
{!{ tmpl.Exec "update_comment_on_start" $workflowName | strings.Indent 6 }!}
{!{ tmpl.Exec "login_dev_registry_step" . | strings.Indent 6 }!}
{!{ tmpl.Exec "login_rw_registry_step" . | strings.Indent 6 }!}

{!{/*
Pull deckhouse images from cache, tag with channel name and push to dev and prod registries.
Images:
- deckhouse/release-channel image
Destination registries:
- DECKHOUSE_REGISTRY_HOST
- DEV_REGISTRY_PATH
*/}!}
{!{ range $werfEnv := slice "CE" "EE" "FE" "BE" "SE" }!}
      - name: Publish release images for {!{ $werfEnv }!}
        env:
          DECKHOUSE_REGISTRY_HOST: ${{secrets.DECKHOUSE_REGISTRY_HOST}}
          SUSPEND_VERSION: ${{needs.detect_version.outputs.version}}
          WERF_ENV: {!{ $werfEnv }!}
          SKIP_PUSH_FOR_SUSPEND: ${{secrets.SKIP_PUSH_FOR_SUSPEND}}
        run: |
          # SRC_NAME is a name of image from werf.yaml.
          # SRC is a source image name.
          # DST is an image name for docker push.
          function push_rmi() {
            SRC_NAME=$1
            DST=$2

            enable_push="true"
            if [[ ${GITHUB_REPOSITORY} != "deckhouse/deckhouse" ]]; then
              if [[ ${SKIP_PUSH_FOR_SUSPEND} == "true" ]]; then
                enable_push="false"
                echo "⚓️ ❎ [$(date -u)] SKIP_PUSH_FOR_SUSPEND=true, skip running 'docker image push ${DST}'."
              fi
            fi

            if [[ ${enable_push} == "true" ]] ; then
              echo "⚓️ 📤 [$(date -u)] Push '${SRC_NAME}' image as ${DST}."
              docker image push ${DST}
            fi

            echo "⚓️ 🧹 [$(date -u)] Remove local tag for '${SRC_NAME}'."
            docker image rmi ${DST} || true;
          }

          # Some precautions.
          shouldExit1=
          if [[ -z ${DEV_REGISTRY_PATH} ]] ; then
            echo "::error title=Missed variable::DEV_REGISTRY_PATH is not set. Define destination registry in secrets."
            shouldExit1=yes
          fi
          if [[ -z ${WERF_ENV} ]] ; then
            echo "::error title=Missed variable::WERF_ENV is not set. Cannot deploy unknown edition, only ce, ee and fe are allowed in inputs."
            shouldExit1=yes
          fi
          if [[ -z ${SUSPEND_VERSION} ]] ; then
            echo "::error title=Missed version::Suspend version not detected. Use suspend_tag input or run workflow from tag."
            shouldExit1=yes
          fi
          if [[ -n ${shouldExit1} ]] ; then
            exit 1
          fi

          echo "Suspend version '${SUSPEND_VERSION}' for {!{ $werfEnv }!} edition".

          # Variables
          #   1. Edition and channel.
          # CE/EE/FE/BE/SE -> ce/ee/fe/be/se
          REGISTRY_SUFFIX=$(echo ${WERF_ENV} | tr '[:upper:]' '[:lower:]')
          RELEASE_CHANNEL={!{ $channel }!}

          echo "⚓️ 💫 [$(date -u)] Start publishing 'release-channel suspend' image for '${REGISTRY_SUFFIX}' edition onto '${RELEASE_CHANNEL}' release channel."

          #   2. Prod registry: use github packages if DECKHOUSE_REGISTRY_HOST not set (run in the test repo).
          DST_REGISTRY_PATH=${DECKHOUSE_REGISTRY_HOST}/deckhouse
          if [[ -z "${DECKHOUSE_REGISTRY_HOST}" ]]; then
            DST_REGISTRY_PATH="${GHA_TEST_REGISTRY_PATH}"
            echo "⚓️ 🧪 [$(date -u)] DECKHOUSE_REGISTRY_HOST is empty. Publish to Github Container Registry '${DST_REGISTRY_PATH}'"
          fi

          #   3. Build and publish release-channel image to prod registry.
          SUSPEND_VERSION_IMAGE=${DST_REGISTRY_PATH}/${REGISTRY_SUFFIX}/release-channel:${RELEASE_CHANNEL}
          echo "⚓️ 🛠 [$(date -u)] Build 'release-channel suspend' image as '${SUSPEND_VERSION_IMAGE}'."

          echo "{\"version\": \"${SUSPEND_VERSION}\", \"suspend\": true}" > version.json
          cat <<EOF >Dockerfile
          FROM scratch
          COPY version.json version.json
          EOF
          docker build . -t "${SUSPEND_VERSION_IMAGE}"

          push_rmi 'release-channel suspend' "${SUSPEND_VERSION_IMAGE}"


{!{- end }!}

{!{ tmpl.Exec "update_comment_on_finish" (slice "job,final" $workflowName) | strings.Indent 6 }!}

{!{ end -}!}
